package com.andnnl.utils;

import cn.hutool.core.util.StrUtil;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.utils.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * https://cloud.tencent.com/developer/article/1130020
 * Created by chenss on 2021/10/18.
 */
public class ZipUtil {
    private static final Logger logger = LoggerFactory.getLogger(ZipUtil.class);
    public static final Charset GBK = Charset.forName("GBK");
    public static final Charset UTF8 = Charset.forName("UTF-8");

    /**
     * 解决文件
     * @param inputFile
     * @param destDirPath
     * @return 文件列表
     * @throws Exception
     */
    public static List<String> unzip2(String inputFile,String destDirPath) throws Exception {
        List<String> rs=new ArrayList<>();
        File srcFile = new File(inputFile);
        // 判断源文件是否存在
        if (!srcFile.exists()) {
            throw new Exception(srcFile.getPath() + "所指文件不存在");
        }
        //默认用压缩文件名作为解压路径
        destDirPath = !StrUtil.isAllBlank(destDirPath)?destDirPath:inputFile.replaceAll("\\.([zZ][iI][pP]) +?$", "");
        //创建压缩文件对象
        ZipFile zipFile = new ZipFile(srcFile, Charset.forName("GBK"));
        //开始解压
        Enumeration<?> entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            ZipEntry entry = (ZipEntry) entries.nextElement();
            // 如果是文件夹，就创建个文件夹
            if (entry.isDirectory()) {
                srcFile.mkdirs();
            } else {
                // 如果是文件，就先创建一个文件，然后用io流把内容copy过去
                File targetFile = new File(destDirPath + File.separator + entry.getName());
                // 保证这个文件的父文件夹必须要存在
                if (!targetFile.getParentFile().exists()) {
                    targetFile.getParentFile().mkdirs();
                }

                targetFile.createNewFile();
                // 将压缩文件内容写入到这个文件中
                InputStream is = zipFile.getInputStream(entry);
                FileOutputStream fos = new FileOutputStream(targetFile);
                int len;
                byte[] buf = new byte[1024];
                while ((len = is.read(buf)) != -1) {
                    fos.write(buf, 0, len);
                }
                // 关流顺序，先打开的后关闭
                fos.close();
                is.close();
                rs.add(targetFile.getAbsolutePath());
            }
        }
        return rs;
    }

    public static List<String> unzip(File zipFile, String descDir) {
        List<String> rs=new ArrayList<>();
        //默认用压缩文件名作为解压路径
        descDir = !StrUtil.isAllBlank(descDir)?descDir:zipFile.getAbsolutePath().replaceAll("\\.([zZ][iI][pP]) *?$", "");
        try (ZipArchiveInputStream inputStream = getZipFile(zipFile)) {
            File pathFile = new File(descDir);
            if (!pathFile.exists()) {
                pathFile.mkdirs();
            }
            ZipArchiveEntry entry = null;
            while ((entry = inputStream.getNextZipEntry()) != null) {

                if (entry.isDirectory()) {
                    String dirName=getName(entry.getRawName());
//                    String fn=new String(entry.getRawName(),Charset.forName("GBK"));
                    File directory = new File(descDir, dirName);
                    directory.mkdirs();
                } else {
                    OutputStream os = null;
                    try {
                        String fn=getName(entry.getRawName());
//                        File file = new File(descDir, entry.getName());//中文乱码
                        File file = new File(descDir, fn);
                        file.getParentFile().mkdirs();//文件名有可能是带有目录的，先建目录
                        os = new BufferedOutputStream(new FileOutputStream(file));
                        //输出文件路径信息
                        logger.info("解压文件的当前路径为:{}", file.getAbsolutePath());
                        IOUtils.copy(inputStream, os);
                        rs.add(file.getAbsolutePath());
                    } finally {
                        IOUtils.closeQuietly(os);
                    }
                }
            }
//            final File[] files = pathFile.listFiles();
//            if (files != null && files.length == 1 && files[0].isDirectory()) {
//                // 说明只有一个文件夹
//                FileUtils.copyDirectory(files[0], pathFile);
//                //免得删除错误， 删除的文件必须在/data/demand/目录下。
//                boolean isValid = files[0].getPath().contains("/data/www/");
//                if (isValid) {
//                    FileUtils.forceDelete(files[0]);
//                }
//            }
            logger.info("******************解压完毕********************");

        } catch (Exception e) {
            logger.error("[unzip] 解压zip文件出错", e);
        }
        return rs;
    }

    private static ZipArchiveInputStream getZipFile(File zipFile) throws Exception {
        return new ZipArchiveInputStream(new BufferedInputStream(new FileInputStream(zipFile)));
    }

    private static String getName(byte[] rawName) {
        String fnGBK=new String(rawName, GBK);
        if(Arrays.equals(fnGBK.getBytes(GBK), rawName)) {
            logger.info(GBK.name()+" "+fnGBK);
            return fnGBK;
        }
        String fnUTF8=new String(rawName, UTF8);
        if(Arrays.equals(fnUTF8.getBytes(UTF8), rawName)) {
            logger.info(UTF8.name()+" "+fnUTF8);
            return fnUTF8;
        }
        return fnGBK;
    }
    public static void main(String[] args) throws Exception {
        String inputFile="asdkjf.zip.alskdjf.zip.ZiP  ";
        String rs=inputFile.replaceAll("\\.([zZ][iI][pP]) +?$", "");
        System.out.println(rs);

//        List<String> list = unzip(new File("E:\\号码优化\\YhMobile_500041可优化名单.zip"), "");
//        System.out.println(list);
        List<String> list2 = unzip(new File("E:\\号码优化\\YhMobile_500041可优化名单2.zip"), "");
        System.out.println(list2);
    }
}
